import numpy as np
import pandas as pd


def data_copy(dataframe, column_name, filt_len):
    lake_index = find_index(dataframe, column_name)
    # 筛选出那些部分的缺失数据需要进行复制填充
    lake_index = [i for i in lake_index if len(i) >= filt_len]
    print(f"len: {len(dataframe)}")
    print(lake_index)

    for item in lake_index:
        print(item)
        # 确定空白片段的年份范围,在copy时绕过这些年份
        gap = len(item) // (8 * 365)
        print(gap)
        # 将一串坐标切分为几个小份
        sub_list = np.array_split(np.array(item), filt_len)
        for list in sub_list:
            # 确定边界
            start = list[0]
            end = list[-1]
            # 确定随机年份的区间
            jump_scope = [-2, -1, 1, 2]
            if start - (365 * 8 * (gap + 2)) < 0:
                jump_scope = [1 + gap, 2 + gap, 3 + gap]
            elif end + (365 * 8 * (gap + 2)) > len(dataframe):
                jump_scope = [-1 - gap, -2 - gap, -3 - gap]
            # 选择此区间需要复制的年份数据
            jump = np.random.choice(jump_scope) * 365 * 8
            j_start = start + jump
            j_end = end + jump
            copy_values = dataframe.loc[j_start: j_end, column_name].copy().values.tolist()
            print(f"{jump_scope} : {jump/365/8}")
            print(f"[{start,end}] -> [{j_start},{j_end}] : {copy_values}")
            dataframe.loc[start: end, column_name] = copy_values

    return dataframe


def date_fill(dataframe, index_name, start_date, end_date, frequence):
    # 设定时间序列为倒序排序
    dataframe[index_name] = pd.to_datetime(dataframe[index_name], format="%d.%m.%Y %H:%M")
    dataframe.sort_index(ascending=False, inplace=True)

    # 设置日期列为索引值
    dataframe = dataframe.set_index(index_name)
    # 获取正确完整的日期序列
    date_range = pd.date_range(start=start_date, end=end_date, freq=frequence)
    # 按照完整的日期序列补充缺失的部分
    dataframe = dataframe.reindex(index=date_range)
    # 将索引值恢复成默认
    dataframe = dataframe.reset_index()
    # 更改日期的列名为原值
    dataframe.rename(columns={'index': '当地时间'}, inplace=True)

    return dataframe


# 找出空值部分对应的边缘下标
def find_index(dataframe, column_name):
    # 找出为空值的样本下标(注意!该列的最后一个值不要为空!)
    NaNArray = np.where(pd.isna(dataframe[column_name]))[0]
    print(column_name)
    result = []
    temp = []

    # 将连续的下标分组统计,找到边缘
    for item in NaNArray:
        if len(temp) == 0 or temp[-1] + 1 == item:
            temp.append(item)
        else:
            if len(temp) >= 1:
                result.append(temp)
            temp = [item]
    if len(temp) >= 1:
        result.append(temp)

    print(result)
    return result


# 按空位前后的数值等差填充
def smooth_fill(dataframe, column_name):
    # 找出空值的样本的边界下标
    lack_index = find_index(dataframe, column_name)
    # 按分组情况依次计算填充值并填充
    for item in lack_index:
        front = item[-1] + 1
        back = item[0] - 1
        # 针对最后一项为空值的特例
        if item[-1] + 1 == len(dataframe):
            fill_value = dataframe.loc[back, column_name]
            for index in range(len(item)):
                dataframe.loc[back + index + 1, column_name] = fill_value
            continue
        # 正常均值填充
        gap = (dataframe.loc[front, column_name] - dataframe.loc[back, column_name]) / (front - back)
        for index in range(len(item)):
            dataframe.loc[back + index + 1, column_name] = round((dataframe.loc[back + index, column_name] + gap), 1)

    return dataframe


# 取空位前一个有效数值填充空位
def solid_fill(dataframe, column_name):
    # 找出为空值样本的边界下标
    lake_index = find_index(dataframe, column_name)
    # 按分组情况向下填充
    for item in lake_index:
        back = item[0] - 1
        fill_value = dataframe.loc[back, column_name]
        for index in range(len(item)):
            dataframe.loc[back + index + 1, column_name] = fill_value

    return dataframe

